#include <CGalaxy.h>



CGalaxy::CGalaxy() {
  parametersInitialized = false;
  average = count = 0;
  //  loadSpectra();


}




void CGalaxy::RandomizeSpectra() {
  for (int i=0;i<spectra.size();i++) {
    float val = rand()%1000 / 1000.0;
    spectra[i]->scaleX(0.95 + val*0.1);
  }
}


void CGalaxy::setupComponentWavelength(double wavelength) {
  for (int j=0;j<components.size();j++) {
    components[j]->strength = components[j]->componentParams.strength;
    if (components[j]->componentParams.spectrum!=0) {

      double scaling = components[j]->componentParams.spectrum->getValAtScaledIndex(wavelength);
      components[j]->strength = components[j]->componentParams.strength * scaling;
    }
  }
    
}


void CGalaxy::RandomParameters() {

  int i = rand()%11 +1;
  int j = rand()%11 +1;
  params.windingB = 0.05*i;
  params.windingN = 2*j*pow(params.windingB, 1.0);

  PerlinScale = 9.0 + rand()%16;

  // Perlin scale random shift, nothing physical

  parametersInitialized = true;

  
}



void CGalaxy::InitializeFromFile(string file, CRenderingParams& RP) {
  try {
  CIniFile f(file);
  params.axis = f.getvector("axis");
  //params.orientation = f.getvector("orientation");
  params.noArms = f.getint("no_arms");
  if (params.noArms>=1) params.arm1 = f.getdouble("arm1");
  if (params.noArms>=2) params.arm2 = f.getdouble("arm2");
  if (params.noArms>=3) params.arm3 = f.getdouble("arm3");
  if (params.noArms>=4) params.arm4 = f.getdouble("arm4");
  
  params.bulgeDust = f.getdouble("bulge_dust");
  //params.bulgeSize = f.getdouble("bulge_size");

   params.bulgeAxis = f.getvector("bulge_axis");

  params.windingB = f.getdouble("winding_B");
  params.windingN = f.getdouble("winding_N");

  params.innerTwirl = f.getdouble("innerTwirl");

  //params.dustScale = f.getdouble("dust_scale");
  //params.diskScale = f.getdouble("disk_scale");
  
  int no_components = f.getint("no_components");
  components.clear();

  params.rotSign = CMath::sgn((RP.camera-RP.target).Dot(params.orientation));
  params.camera = RP.camera;

  for (int i=0;i<no_components;i++) {
    string name ="component"+CUtil::toString(i+1)+ "_";
    string type = f.getstring(name+"type");
    CComponentParams cp;
    cp.strength = f.getdouble(name + "intensity_modifier");
    cp.arm = f.getdouble(name + "armstrength");
    cp.z0 = f.getdouble(name + "z0");
    cp.r0 = f.getdouble(name + "r0");
    cp.scale = f.getdouble(name + "scale");
    cp.winding = f.getdouble(name + "winding");
    CGalaxyComponent* c = 0;
    cp.spectrum = spectra[ f.getint(name+"spectrum")];

    // Ignore inactive stuff
    int isActive = f.getdouble(name + "active");

    if (isActive == 1) { 
    if (type=="BULGE")
      c = new CGalaxyComponentBulge(&params, cp);
    else if (type=="STARS")
      c = new CGalaxyComponentStars(&params, cp);
    else if (type=="DISK")
      c = new CGalaxyComponentDisk(&params, cp);
    else if (type=="DUST")
      c = new CGalaxyComponentDust(&params, cp);

    else throw new string("Unknown component type in " + file + " : " + type);
    
    c->perlin = params.perlin;
    components.push_back(c);
    }
  }
  }
  catch (string s) {
    cout << s << endl;
    exit(1);
  }

}


void CGalaxy::loadSpectra(vector<CGraph*>& sp) {
  spectra.clear();
  for (int i=0;i<sp.size();i++) {
    CGraph* g = new CGraph();
    g->Copy(*sp[i]);
    spectra.push_back(g);
  }


}



/*void CGalaxy::RenderGalaxiesFromParticles(C2DImage& target, float sizes, CParticles& p, float w, float dx, float dy, int type, int max) {
  
  CCounter cnt(max, "Rendering galaxies");
  int N = target.Width;
  int current = 0;
  //for (int i=0;i<p.objects.size
  for (int i=0;i<p.objects.size();i++)
    p.objects[i].flag = 0;
  

  while (current<max) {

    int i = rand()%p.objects.size();
    while ( p.objects[i].flag == 1)  {
      i = rand()%p.objects.size();
    }


    int x = (N/2) + ((p.objects[i].P.x - dx)*N) * w;
    int y = (N/2) + ((p.objects[i].P.y - dy)*N) * w;
    if ( x >= 0 && x < N && y >= 0 && y < N ) 
      {
	int size = sizes*(abs(CMath::RandomGauss())*35.0 + 5.0);
	if (rand()%15==1)
	  size*=1.5;

	if (rand()%15==1)
	  size*=1.5;

	
	float f = size;//abs(CMath::RandomGauss())*size*1.0 + 0.1;
	CGalaxy galaxy;
	//	galaxy.RenderGalaxy(size);
	galaxy.image.Normalize(256);
	galaxy.image.Stamp(x,y,target,0.01*f);

	current++;
	cnt.Tick();
	p.objects[i].flag = 1;
      }
      
  }

}


*/
